/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.editor;

import java.util.*;
import self.awt.event.*;

import self.gee.*;
import self.gee.editor.*;
import self.amigo.editor.layer.*;

public class BasicEditor implements IDiagramEditor {
  private IEditorListener   listener;
  private GridLayer         grid = new GridLayer(); 
  private ILayer            handles = null;
  private IDiagram          source;  
  private IDiagramToolSet   toolbar;
  private IDiagramInspector inspector;
  private EventManager      controller = new EventManager();
  
  private SelectionTool     selector = new SelectionTool();
  private CommandManager    cmdHistory;
  
  private HashMap           inspectorProperties = new HashMap();
  private boolean           deleting;
  private boolean           autoCommit = true;
  
  public BasicEditor() {
    selector.setEditor( this );
    selector.setEventManager( controller );
    handles = selector.getGrabHandleLayer();
  }
  
  public void mount( IDiagram context ) {
    source = context;
    source.setBackground( grid );
    source.setForeground( handles );
    grid.setDiagram( source );
    controller.diagramLayer = source.getContext();
    cmdHistory = DiagramCommandUtils.getManager( this.getSource() );
    if ( loadToolBar() )
      setSelectionTool();
    selector.clearSelection();
  }
  
  public void unmount(){
    if ( source != null ) {
      source.setBackground( null );
      source.setForeground( null );
      grid.setDiagram( null );
      source = null;
      cmdHistory = null;
    }
    controller.diagramLayer = null;
  }
  
  public IEditingListener getEditingController() {
    return controller;
  }

  public void executeCommand( int executeType, ICommand cmd ) {
    switch ( executeType ) {
      case ICommand.ET_PRE_EXECUTED:  cmdHistory.execute( cmd, true ); break;
      case ICommand.ET_EXECUTE:       cmdHistory.execute( cmd, false ); break;
      case ICommand.ET_UNDO:          cmdHistory.undo(); break;
      case ICommand.ET_REDO:          cmdHistory.redo(); break;
    }
    if ( listener != null )
      listener.commandExecuted( executeType, cmd, cmdHistory );
  }
  
  public CommandManager getCommandHistory() {
    return cmdHistory;
  }
  
  public void prepareToolbar( IDiagramToolSet tools ) {
    toolbar = tools;
  }
  
  public void prepareInspector( IDiagramInspector insp ) {
    inspector = insp;
  }
  
  public void inspectSelectedObjects( List selectedItems ) {
    Object viewInPropertySheet = null;
    int count = selectedItems.size();
    if ( (count == 0) || (count > 1) ) {
      viewInPropertySheet = source;
    } else
      viewInPropertySheet = selectedItems.get( 0 );
    IPropertySheet lastSheet = inspector.getSheet();
    IPropertySheet toInstall = PropertySheetManagerUtils.getPropertySheet( viewInPropertySheet.getClass() );
    if ( isAutoCommit() && !isDeleting() && (lastSheet != null) ) {
      if ( viewInPropertySheet == lastSheet.getObjectUnderInspection() ) {
        notifySelectionChanged( selectedItems );
        return;
      } else
        lastSheet.accept();
    }
    if ( toInstall != lastSheet ) {
      if ( lastSheet != null ) 
        lastSheet.dispose();
      if ( toInstall == null )
        inspector.reset();
      else {
        toInstall.prepare( this, inspectorProperties );
        inspector.install( toInstall );
      }
    }
    if ( toInstall != null ) {
      toInstall.inspect( viewInPropertySheet );
    }
    notifySelectionChanged( selectedItems );
  }

  private void notifySelectionChanged( List selectedItems ) {
    if ( listener != null ) 
      listener.selectionChanged( selectedItems, selectedItems.size() );
  }
  
  public void setSelectionTool() {
    toolbar.selectDefault();
    controller.setEditingTool( selector );
  }
  
  public IDiagram getSource() {
    return source;
  }
  
  public void getSelectedElements( List store ) {
    selector.getSelectedItems( store );
  }
  
  public void setSelectedElements( List newSelection ) {
    IDiagramLayer layer = source.getContext();
    layer.beginUpdate();
    selector.setSelectedItems( newSelection );
    layer.endUpdate();
    if ( listener != null )
      listener.selectionChanged( newSelection, newSelection.size() );
  }
  
  public void selectAllElements() {
    ArrayList allElems = new ArrayList();
    IDiagramLayer layer = source.getContext();
    layer.getElements( allElems );
    setSelectedElements( allElems );
  }
  
  public boolean isDeleting() {
    return deleting;
  }
  
  public void setDeleting( boolean currentlyDeleting ) {
    deleting = currentlyDeleting;
  }
  
  public boolean isAutoCommit() {
    return autoCommit;
  }
  
  public void setAutoCommit( boolean ac ) {
    autoCommit = ac;
  }
  
  public void setEditorListener( IEditorListener l ) {
    listener = l;
  }
  
  private boolean loadToolBar() {
    boolean load = (toolbar != null) && (source != null);
    if ( load ) {
      List toolClasses = ToolsManagerUtils.getToolSet( source.getClass() );
      ArrayList actions = new ArrayList( toolClasses.size() + 1 );
      actions.add( selector.getAction() );
      Iterator itr = toolClasses.iterator();
      while ( itr.hasNext() ) {
        Class toolClass = (Class) itr.next();
        IEditingTool tool;
        try {
          tool = (IEditingTool) toolClass.newInstance();
        } catch ( Exception err ) {
          err.printStackTrace();
          continue;
        }
        tool.setEditor( this );
        tool.setEventManager( controller );
        actions.add( tool.getAction() );
      }
      toolbar.install( actions );
    }
    return load;
  }
}
